package com.yjzx.care;

import com.yjzx.care.base.BaseClass;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yjzx
 * @date 2023/12/25
 * @description 所有核心对象外界获取都要实现此接口
 */
public interface MyInterface {

    Map<Class<?>, Reference<MethodHandle>> CONSTRUCTOR_MAP = new HashMap<>(16);

    /**
     * 获取泛型的对象（需实现本接口）
     *
     * @param clazz 接口实现对象
     * @param <T>   要获取的对象类型
     * @return 泛型对象
     */
    static <T extends MyInterface> T newInstance(BaseClass<T> clazz) {
        try {
            Class<?> aClass = clazz.getGenericityClass();
            MethodHandle handle = toConstructorMethodHandle(aClass);
            return (T) handle.invoke();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 提高创建效率将反射获取改为methodHandle获取
     * @param aClass
     * @return
     */
    static MethodHandle toConstructorMethodHandle(Class<?> aClass) {
        if (aClass != null && MyInterface.class.isAssignableFrom(aClass)) {
            Reference<MethodHandle> ref;
            if ((ref = CONSTRUCTOR_MAP.get(aClass)) == null || ref.get() == null) {
                try {
                    MethodHandle methodHandle;
                    methodHandle = MethodHandles.lookup().findConstructor(aClass, MethodType.methodType(void.class));
                    CONSTRUCTOR_MAP.put(aClass, new SoftReference<>(methodHandle));
                    return methodHandle;
                } catch (Throwable ignored) {
                    throw new RuntimeException(aClass+"无法正确无参构造器");
                }
            } else {
                return ref.get();
            }
        }
        throw new RuntimeException("无法正确获取函数式关键字对象");
    }
}
